其他
iOS 隐形水印之 LSB 实现
本文字数:2581字
预计阅读时间:7分钟
在音视频的领域里,其涵盖的知识点繁多,学习方向也很多。而本篇就是一篇比较入门的文章它简单地介绍如何在 iOS 上读取图片 RGB 数据,并通过修改最后一位 bit 来记录数字水印的信息下面就介绍《隐形水印之 iOS 实现》
技术
背景
水 印
L S B
(255, 255, 255) -取255-> 1111 1111 -> 把最后一位(1 => 0) -> 1111 1110 -放回-> (254, 255, 255)
数字
水印
应用
场景
QFImageMaskMan
实 现
static let markBin: [QFLSBMarkBin] = [.key, .lengthBit, .length, .info]
(扩展来变更 length 所占的字节) | ||
encode & decode
class func baseEncode(data: UnsafeMutablePointer<UInt8>, infoData: Data, width w: Int, height h: Int) {
let kQHKeyData = kQFkey.data(using: .utf8)!
let kQHKeyDataCount = kQHKeyData.count
let kLenghtCount = kLengthBit
let markCount = kQHKeyDataCount + kLengthBitCount + kLenghtCount + infoData.count
var bStop = false
var markIndex = -1
var markIndexText: Int = 0
var markBin: QFLSBMarkBin?
var markLengthBitCount = 0
// 1、读取原数据
for y in 0..<h {
if bStop {
break;
}
for x in 0..<w {
let index = (y * w + x)
let markIndexTemp = index / 8
if markIndexTemp >= markCount {
bStop = true
break
}
// 2、水印信息的计算
if markIndex != markIndexTemp {
markIndex = markIndexTemp
if markIndex < kQHKeyDataCount {
markBin = .key
markIndexText = Int(kQHKeyData[markIndex])
}
else if markIndex < kQHKeyDataCount + kLengthBitCount {
markBin = .lengthBit
markIndexText = kLengthBit
}
else if markIndex < kQHKeyDataCount + kLengthBitCount + kLenghtCount {
markLengthBitCount += 1
markBin = .length
if markLengthBitCount == 1 {
markIndexText = markCount%256
}
else if markLengthBitCount == 2 {
markIndexText = Int(markCount>>8)
}
else {
bStop = true
break
}
}
else if markIndex < markCount {
markBin = .info
markIndexText = Int(infoData[markIndex - (kQHKeyDataCount + kLengthBitCount + kLenghtCount)])
}
}
if markBin == nil {
bStop = true
break
}
// 3、读取原数据 & 获取最低有效位
let offset = 4 * index
let red = data[offset+1]
let redBinary = red % 2
let markIndexTextBinaryIndex = index % 8
let markIndexTextBinary = Int((markIndexText / (1<<Int(markIndexTextBinaryIndex))) % 2)
// 4、最低有效位记录
if redBinary != markIndexTextBinary {
if markIndexTextBinary == 0 {
if red == 255 {
data[offset+1] = 254
}
else {
data[offset+1] = red + 1
}
}
else {
if red == 0 {
data[offset+1] = 1
}
else {
data[offset+1] = red - 1
}
}
}
}
}
}
// 逻辑上与 baseEncode 相同,读取原数据后记录到对应的水印数据信息上。
class func baseDecode(data: UnsafeMutablePointer<UInt8>, width w: Int, height h: Int) -> (result: Bool, info: String) {
// ......
return (false, "解密");
}
补 充
1、这里需要注意在截图类的逻辑那部分,有如下的函数 & 执行(加密后的图片再执行)
将加密后将图片先缓存本地,再获从缓存本地的图片获取出来进行分享和保存相册,这样加密的数才不会由于保存相册或者直接分享而导致数据会丢失。目前测试分享QQ和钉钉数据解码正常,而微信会丢失的。
private func toPng() -> Bool
if !toPng() {
print("showScreenshot toPng 失败")
return
}
let text = "QFScreenshot" as NSString
let p = CGPoint(x: 20, y: 160)
text.draw(at: p, withAttributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16), NSAttributedString.Key.foregroundColor: UIColor(white: 0.5, alpha: 1)])
总 结
其他
用途
改进的
隐形水印
一种改进的LSB信息隐藏算法研究与实现[3]🔺见文末
[1]🔺QFImageMaskMan:
https://gitee.com/chenqihui/QFImageMaskDemo
也许你还想看
(▼点击文章标题或封面查看)
加入搜狐技术作者天团
千元稿费等你来!
戳这里!☛